﻿namespace Jhong.OWINSession.OWINCookie
{
    using System;
    using System.Collections.Generic;
    using Env = System.Collections.Generic.IDictionary<string, object>;

    internal class CookieFactory
    {
        public static IDictionary<string, string> GetCookies(Env env)
        {
            var dic = env.Get<IDictionary<string, string>>("Microsoft.Owin.Cookies#dictionary");
            if (null == dic)
            {
                dic = new Dictionary<string, string>(StringComparer.Ordinal);
                env.Set<IDictionary<string, string>>("Microsoft.Owin.Cookies#dictionary", dic);
            }
            var header = env["owin.RequestHeaders"] as IDictionary<string, string[]>;
            string cookies = null;
            string[] headerUnmodified = null;
            if (header.TryGetValue("Cookie", out headerUnmodified)) cookies = string.Join(",", headerUnmodified);
            if (env.Get<string>("Microsoft.Owin.Cookies#text") != cookies)
            {
                dic.Clear();
                ParseDelimited(cookies, new char[] { ';', ',' }, (string name, string value, object state) =>
                {
                    IDictionary<string, string> dictionary = (IDictionary<string, string>)state;
                    if (!dictionary.ContainsKey(name))
                    {
                        dictionary.Add(name, value);
                    }
                }, dic);
                env.Set<string>("Microsoft.Owin.Cookies#text", cookies);
            }

            return dic;
        }

        private static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, object state)
        {
            int length = text.Length;
            int num = text.IndexOf('=');
            if (num == -1)
            {
                num = length;
            }
            int num2;
            for (int i = 0; i < length; i = num2 + 1)
            {
                num2 = text.IndexOfAny(delimiters, i);
                if (num2 == -1)
                {
                    num2 = length;
                }
                if (num < num2)
                {
                    while (i != num && char.IsWhiteSpace(text[i]))
                    {
                        i++;
                    }
                    string text2 = text.Substring(i, num - i);
                    string text3 = text.Substring(num + 1, num2 - num - 1);
                    callback(Uri.UnescapeDataString(text2.Replace('+', ' ')), Uri.UnescapeDataString(text3.Replace('+', ' ')), state);
                    num = text.IndexOf('=', num2);
                    if (num == -1)
                    {
                        num = length;
                    }
                }
            }
        }
    }
}